package com.mycase.im.boot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mycase.im.boot.entity.database.*;
import com.mycase.im.boot.exception.CustomException;
import com.mycase.im.boot.mapper.ChatGroupUserMapper;
import com.mycase.im.boot.mapper.GroupMessageBodyMapper;
import com.mycase.im.boot.mapper.MessageMapper;
import com.mycase.im.boot.mapper.UserMapper;
import com.mycase.im.boot.service.ChatGroupUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author ZhuHJay
 * @Date 2021/9/2 17:45
 */
@Service
@Transactional(rollbackFor = CustomException.class)
public class ChatGroupUserServiceImpl extends ServiceImpl<ChatGroupUserMapper, ImChatGroupUser> implements ChatGroupUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private GroupMessageBodyMapper groupMessageBodyMapper;
    @Autowired
    private MessageMapper messageMapper;

    @Override
    public void refreshUsersToGroup(ImChatGroup imChatGroup, ArrayList<String> toGroupUsersId) {
        // 创建人也是一个用户, 所以也把创建者放到用户例表中
        toGroupUsersId.add(0, imChatGroup.getCreateUser());
        // 获取创建人的信息
        ImUser createUserInfo = userMapper.selectById(imChatGroup.getCreateUser());

        // 准备一份 用于绑定群聊和用户的JavaBean对象, 因为同一批次添加的用户数据都是相同的
        ImChatGroupUser imChatGroupUser = new ImChatGroupUser();
        imChatGroupUser.setJoinTime(imChatGroup.getCreateTime());
        imChatGroupUser.setChatGroupId(imChatGroup.getId());
        // 准备一份 用于发送系统消息的JavaBean对象, 系统通知的消息内容别具一格
        ImMessage imMessage = new ImMessage();
        // 设置消息发送的日期
        imMessage.setSendTime(new Date());
        // 设置消息的类型 -> 群聊
        imMessage.setType(1);
        // 设置消息是否为通知类型 -> 系统通知
        imMessage.setNotify(1);
        // 设置消息所对应的群聊
        imMessage.setGroupId(imChatGroup.getId());
        // 设置发送人(就是群聊的创建者)
        imMessage.setFromId(createUserInfo.getId());

        // 开始进行用户的创建
        toGroupUsersId.forEach(userId ->
            insertUserToGroupAndCreatedMessage(
                    imChatGroup,
                    imChatGroupUser,
                    createUserInfo,
                    userId,
                    toGroupUsersId,
                    imMessage)
        );
    }

    /** 添加用户到群聊中并且创建聊天记录: 单个用户
     * @param imChatGroup 群聊信息
     * @param imChatGroupUser 用来绑定群聊和用户的JavaBean
     * @param inviteUserInfo  邀请人的信息
     * @param willInGroupUserId 将要加入到群聊的用户id
     * @param groupUsersId 当前群聊的所有用户id(也要包括将要添加进来的用户id)
     * @param imMessage 系统通知内容对象
     */
    private void insertUserToGroupAndCreatedMessage(
            ImChatGroup imChatGroup,
            ImChatGroupUser imChatGroupUser,
            ImUser inviteUserInfo,
            String willInGroupUserId,
            List<String> groupUsersId,
            ImMessage imMessage){
        /* 已知创建了一个群聊, 也就仅仅创建了群聊而已, 其他信息都还没有处理的情况下
            具体做法如下:
                1. 先将用户绑定群聊 -> im_chat_group_user
                2. 邀请的消息记录生成 -> im_message
                    * 每发送一次消息, 都需要一个消息内容体 -> im_group_message_body
                        * 消息内容体中需要有当前群聊所有的联系人
        */
        // 1. 首先进行该用户于群聊建立关系
        imChatGroupUser.setUserId(willInGroupUserId);
        // 进行数据库保存
        if( !save(imChatGroupUser) ){
            throw new CustomException("操作失败, 请重试");
        }
        // 2. 邀请的系统通知记录生成
        // 在此之前需要创建一个群组消息体( 该聊天记录面向的联系人 )
        ImGroupMessageBody imGroupMessageBody = new ImGroupMessageBody();
        // 设置消息为已读状态, 系统通知就不进行未读处理了
        imGroupMessageBody.setReadStatus(1);
        groupUsersId.forEach(userId -> {
            imGroupMessageBody.setUserId(userId);
            if( groupMessageBodyMapper.insert(imGroupMessageBody) != 1 ){
                throw new CustomException("操作失败, 请重试");
            }
        });
        // 开始进行系统通知的存储了
        // 设置接收人是哪个消息体
        imMessage.setToId(imGroupMessageBody.getMessageBodyId());
        // 如果此时要加入到群聊的用户id是创建者, 那么就是发送创建群聊的通知消息
        if( imChatGroup.getCreateUser().equals(willInGroupUserId) ){
            imMessage.setContent(inviteUserInfo.getNikeName() + " 创建群聊");
        }else{
            // 设置发送的信息
            ImUser willInGroupUserInfo = userMapper.selectById(willInGroupUserId);
            imMessage.setContent(inviteUserInfo.getNikeName() + " 邀请 " + willInGroupUserInfo.getNikeName() + " 加入该群");
        }
        // 添加到数据库中
        if( messageMapper.insert(imMessage) != 1 ){
            throw new CustomException("操作失败, 请重试");
        }
    }

    @Override
    public List<ImChatGroupUser> getGroupListByUserId(String id) {
        QueryWrapper<ImChatGroupUser> imChatGroupUserQueryWrapper = new QueryWrapper<>();
        imChatGroupUserQueryWrapper
                .eq("user_id", id);
        return list(imChatGroupUserQueryWrapper);
    }

    @Override
    public List<ImChatGroupUser> getGroupUserListById(String chatGroupId) {
        QueryWrapper<ImChatGroupUser> imChatGroupUserQueryWrapper = new QueryWrapper<>();
        imChatGroupUserQueryWrapper
                .eq("chat_group_id", chatGroupId);
        // 查询到所有的绑定信息
        List<ImChatGroupUser> list = list(imChatGroupUserQueryWrapper);
        // 然后挨个查询用户信息, 修改到JavaBean中
        list.forEach(item ->
            item.setImUser(userMapper.findById(item.getUserId())) );
        return list;
    }

    @Override
    public void inviteUsersToGroup(String inviteId, ImChatGroup imChatGroup, ArrayList<String> insertUsers) {
        // 获取邀请人的信息
        ImUser inviteUserInfo = userMapper.findById(inviteId);
        // 获取当前群聊的所有用户id
        List<ImChatGroupUser> chatGroupUserList = list(new QueryWrapper<ImChatGroupUser>()
                .eq("chat_group_id", imChatGroup.getId()));
        List<String> groupUsersId = new ArrayList<>();
        chatGroupUserList.forEach(imChatGroupUser ->
                groupUsersId.add(imChatGroupUser.getUserId()) );
        // 新邀请的用户当前也算是群里的一员
        groupUsersId.addAll(insertUsers);

        // 创建一个 绑定群聊的JavaBean 有些数据需要共享
        ImChatGroupUser imChatGroupUser = new ImChatGroupUser();
        imChatGroupUser.setChatGroupId(imChatGroup.getId());
        imChatGroupUser.setJoinTime(new Date());
        // 准备一份 用于发送系统消息的JavaBean对象, 系统通知的消息内容别具一格
        ImMessage imMessage = new ImMessage();
        // 设置消息发送的日期
        imMessage.setSendTime(new Date());
        // 设置消息的类型 -> 群聊
        imMessage.setType(1);
        // 设置消息是否为通知类型 -> 系统通知
        imMessage.setNotify(1);
        // 设置消息所对应的群聊
        imMessage.setGroupId(imChatGroup.getId());
        // 设置发送人 (就是邀请者本人)
        imMessage.setFromId(inviteId);

        // 开始挨个邀请
        insertUsers.forEach(willInGroupUserId ->
                insertUserToGroupAndCreatedMessage(
                        imChatGroup,
                        imChatGroupUser,
                        inviteUserInfo,
                        willInGroupUserId,
                        groupUsersId,
                        imMessage)
        );
    }
}
